package net.discard.filter;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.time.StopWatch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Discard
 * @date 13/02/2120:11
 */
@Order(2)
@WebFilter(filterName = "logFilter", urlPatterns = "/*")
public class LogFilter implements Filter {

    private static final Logger logger = LoggerFactory.getLogger(LogFilter.class);

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();

        ReadableHttpServletRequestWrapper requestWrapper = new ReadableHttpServletRequestWrapper((HttpServletRequest) request);
        ReadableHttpServletResponseWrapper responseWrapper = new ReadableHttpServletResponseWrapper((HttpServletResponse) response);

        boolean isHealthCheck = requestWrapper.getRequestURL().toString().contains("erupt-api")
                || requestWrapper.getRequestURL().toString().contains("assets");

        if (!isHealthCheck) {
            logger.info("收到http请求, url: {}, wrappedParams: {}, wrappedJson: {}, wrappedFiles: {}, headers: {}",
                   requestWrapper.getRequestURL().toString(), requestWrapper.getWrappedParams(),
                    requestWrapper.getWrappedJson(), requestWrapper.getWrappedFiles(), getHeader(requestWrapper));

        }
        chain.doFilter(requestWrapper, responseWrapper);

        if (!isHealthCheck) {
            logger.info("返回http响应耗时: {}ms, responseBody: {}, url: {}, wrappedParams: {}, wrappedJson: {}, wrappedFiles: {}",
                    stopWatch.getTime(), responseWrapper.getResponseBody4Log(),requestWrapper.getRequestURL().toString(),
                    requestWrapper.getWrappedParams(), requestWrapper.getWrappedJson(), requestWrapper.getWrappedFiles()
            );
        }

    }

    @Override
    public void destroy() {

    }

    protected String forLog(Map<String, MultipartFile> wrappedFiles) {
        StringBuilder result = new StringBuilder();
        result.append("[");
        wrappedFiles.forEach((k,v) ->
                result.append("{")
                        .append(k).append(",")
                        .append(v.getOriginalFilename()).append(",")
                        .append(v.getContentType())
                        .append("}").append(","));
        result.append("]");
        return result.toString();
    }


    private String getHeader(ReadableHttpServletRequestWrapper requestWrapper ){
        Map<String, String> map = new HashMap<>();
        Enumeration<String> headerNames = requestWrapper.getHeaderNames();
        if (headerNames == null) {
            return JSONObject.toJSONString(map);
        }
        while (headerNames.hasMoreElements()) {
            String key = headerNames.nextElement();
            String value = requestWrapper.getHeader(key);
            map.put(key, value);
        }
        return JSONObject.toJSONString(map);
    }
}
